<template>
  <div class="image-upload-container">
    <div v-if="mode === 'DESIGN'">
      <div class="design">
        <icon-plus size="28" />
      </div>
      <p>{{ placeholder }} {{ sizeTip }}</p>
    </div>
    <template v-else>
      <div class="picture-card">
        <div class="picture-card__list">
          <div class="picture-card__item" v-for="(item, index) in _value as any" :key="item.fileId">
            <div class="picture-card__item-mask" v-if="!$attrs.disabled">
              <icon-delete @click="handleRemoveFile(index)" />
            </div>
            <a-image v-if="fileUploadComplete.loadingArr[item.fileId] === 100" :src="item.fileUrl" fit="cover" />
            <a-progress
              v-if="fileUploadComplete.loadingArr[item.fileId] !== 100"
              type="circle"
              size="medium"
              :percent="fileUploadComplete.loadingArr[item.fileId]"
            />
          </div>
          <div class="picture-card__item" style="border: 0" v-if="!$attrs.disabled && _value.length < maxNumber">
            <a-upload
              :file-list="_value"
              :show-file-list="false"
              accept="image/*"
              multiple
              :limit="maxNumber"
              :on-before-upload="beforeUpload"
              :custom-request="customUpload"
              @exceed-limit="oneExceed"
              @error="onError"
            >
              <template #upload-button>
                <div class="upload-picture-card">
                  <icon-plus size="28" />
                </div>
              </template>
            </a-upload>
          </div>
        </div>
        <div class="picture-card__tip" v-if="!$attrs.disabled">{{ placeholder }} {{ sizeTip }}</div>
      </div>
    </template>
  </div>
</template>

<script setup lang="ts">
import { computed, useAttrs } from "vue";
import { Message } from "@arco-design/web-vue";
import type { FileItem, RequestOption } from "@arco-design/web-vue";
import { isEmpty } from "lodash";
import { createNewFilename } from "@/utils/upload";
import { generateId } from "@/utils";
import useMultipartOssStore from "@/stores/modules/multipartOssStore";
import useFileUploadComplete from "@/stores/modules/fileUploadComplete";

const $attrs = useAttrs();
const props = defineProps({
  mode: {
    type: String,
    default: "DESIGN"
  },
  required: {
    type: Boolean,
    default: false
  },
  readonly: {
    type: Boolean,
    default: false
  },
  maxSize: {
    type: Number,
    default: 5
  },
  maxNumber: {
    type: Number,
    default: 20
  },
  modelValue: {
    type: Array,
    default: () => []
  },
  placeholder: {
    type: String,
    default: "请选择图片"
  }
});
const emit = defineEmits(["update:modelValue"]);
const multipartOssStore = useMultipartOssStore();
const fileUploadComplete = useFileUploadComplete();

const sizeTip = computed(() => {
  return props.maxSize > 0 ? `| 每张图不超过${props.maxSize}MB` : "";
});
const _value = computed({
  get() {
    if (props.modelValue?.length) {
      props.modelValue.forEach((item: any) => {
        fileUploadComplete.setFileLoading(item.fileId, 100);
      });
    }
    return Array.isArray(props.modelValue) ? props.modelValue : [];
  },
  set(val) {
    emit("update:modelValue", val);
  }
});

const beforeUpload = (file: File) => {
  console.log(file, "<<<<before");
  if (props.maxSize <= 0) {
    Message.error("请设置正确的文件大小！");
    return false;
  }
  const maxSize = file.size / 1024 / 1024 < props.maxSize;
  if (!maxSize) {
    Message.error(`单个文件大小不能超过${props.maxSize}M!`);
    return false;
  }
  return true;
};
const oneExceed = () => {
  Message.error(`最多上传${props.maxNumber}个文件`);
  return false;
};

const fileToBlob = (fileItem: FileItem) => {
  const { uid: fileId, file } = fileItem;
  return {
    fileId,
    name: file?.name,
    size: file?.size,
    type: file?.type,
    fileUrl: URL.createObjectURL(file as File)
  };
};
const customUpload = async (option: RequestOption) => {
  try {
    const { uid: fileId = generateId(), file } = option.fileItem;
    _value.value.push(fileToBlob(option.fileItem));
    fileUploadComplete.setFileLoading(fileId, 0);
    const { file: fileData, objectName } = await createNewFilename(file);
    await multipartOssStore.submit(objectName, fileData, fileId);
    await multipartOssStore.setACL(objectName, "public-read");
    const fileUrl = await multipartOssStore.signatureUrl(objectName);
    fileUploadComplete.setCompleteState(fileId, true);
    const url = fileUrl ? fileUrl.split("?")[0] : "";
    const fileObj = {
      fileUrl: url,
      url,
      fileId,
      fileName: fileData.name
    };
    const index = _value.value.findIndex((item: any) => item.fileId === fileId);
    index !== -1 && (_value.value[index] = { ...fileObj });
    emit("update:modelValue", _value.value);
  } catch (err) {
    console.log(err);
    alert(`文件上传错误：${JSON.stringify(err)}`);
  }
};
const onError = (fileItem: FileItem) => {
  alert(`onError:${JSON.stringify(fileItem)}`);
  console.log("onError>>>", fileItem);
};
const handleRemoveFile = (index: number) => {
  _value.value.splice(index, 1);
};

if (isEmpty(_value.value) && !$attrs.disabled) {
  _value.value = $attrs.defaultValue as any[];
}
</script>

<style lang="scss" scoped>
$picture-card-size: 84px;

.image-upload-container {
  width: 100%;
}
.design {
  :deep(.arco-icon) {
    padding: 10px;
    font-size: xx-large;
    background: white;
    border: 1px dashed #8c8c8c;
  }
}

.upload-picture-card {
  display: flex;
  justify-content: center;
  align-items: center;
  width: $picture-card-size;
  height: $picture-card-size;
  border: 1px solid #cdd0d6;
  background-color: #fafafa;
  overflow: hidden;
  :deep(.arco-icon) {
    font-size: 28px;
    color: #909399;
  }
}

.picture-card {
  @include flex;
  flex-wrap: wrap;
  width: 100%;
  &__list {
    width: 100%;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax($picture-card-size, 1fr));
    grid-gap: 10px;
  }
  &__item {
    @include flex-center;
    position: relative;
    width: 100%;
    height: $picture-card-size;
    cursor: pointer;
    :deep(.arco-upload) {
      width: 100%;
    }
    :deep(.arco-image),
    :deep(.arco-image-img) {
      width: 100%;
      height: 100%;
    }

    &:hover {
      .picture-card__item-mask {
        z-index: 999;
        background-color: rgba(0, 0, 0, 0.5);
      }
    }

    &-mask {
      @include flex-center;
      position: absolute;
      width: 100%;
      height: 100%;
      z-index: -1;
      font-size: 20px;
      transition: background-color 0.3s;

      :deep(.arco-icon) {
        color: #fff;

        & + .arco-icon {
          margin-left: 10px;
        }
      }
    }
  }
  &__tip {
    font-size: 12px;
    color: #606266;
    margin-top: 7px;
  }
}

:deep(.el-progress-circle) {
  width: 84px !important;
  height: 84px !important;
}
</style>
